[][src]Crate pnet

libpnet

libpnet provides a cross-platform API for low level networking using Rust.

There are four key components:

  • The packet module, allowing safe construction and manipulation of packets;
  • The pnet_packet crate, providing infrastructure for the packet module;
  • The transport module, which allows implementation of transport protocols;
  • The datalink module, which allows sending and receiving data link packets directly.

Terminology

The documentation uses the following terms interchangably:

  • Layer 2, datalink layer;
  • Layer 3, network layer;
  • Layer 4, transport layer.

Unless otherwise stated, all interactions with libpnet are in host-byte order - any platform specific variations are handled internally.

Examples

More examples, including a packet logger, and a version of the echo server written at the transport layer, can be found in the examples/ directory.

Ethernet echo server

This (fairly useless) code implements an Ethernet echo server. Whenever a packet is received on an interface, it echo's the packet back; reversing the source and destination addresses.

extern crate pnet;

use pnet::datalink::{self, NetworkInterface};
use pnet::datalink::Channel::Ethernet;
use pnet::packet::{Packet, MutablePacket};
use pnet::packet::ethernet::{EthernetPacket, MutableEthernetPacket};

use std::env;

// Invoke as echo <interface name>
fn main() {
    let interface_name = env::args().nth(1).unwrap();
    let interface_names_match =
        |iface: &NetworkInterface| iface.name == interface_name;

    // Find the network interface with the provided name
    let interfaces = datalink::interfaces();
    let interface = interfaces.into_iter()
                              .filter(interface_names_match)
                              .next()
                              .unwrap();

    // Create a new channel, dealing with layer 2 packets
    let (mut tx, mut rx) = match datalink::channel(&interface, Default::default()) {
        Ok(Ethernet(tx, rx)) => (tx, rx),
        Ok(_) => panic!("Unhandled channel type"),
        Err(e) => panic!("An error occurred when creating the datalink channel: {}", e)
    };

    loop {
        match rx.next() {
            Ok(packet) => {
                let packet = EthernetPacket::new(packet).unwrap();

                // Constructs a single packet, the same length as the the one received,
                // using the provided closure. This allows the packet to be constructed
                // directly in the write buffer, without copying. If copying is not a
                // problem, you could also use send_to.
                //
                // The packet is sent once the closure has finished executing.
                tx.build_and_send(1, packet.packet().len(),
                    &mut |mut new_packet| {
                        let mut new_packet = MutableEthernetPacket::new(new_packet).unwrap();

                        // Create a clone of the original packet
                        new_packet.clone_from(&packet);

                        // Switch the source and destination
                        new_packet.set_source(packet.get_destination());
                        new_packet.set_destination(packet.get_source());
                });
            },
            Err(e) => {
                // If an error occurs, we can handle it here
                panic!("An error occurred while reading: {}", e);
            }
        }
    }
}

Modules

datalink

Support for sending and receiving data link layer packets.

packet

Support for packet parsing and manipulation.

transport

Support for sending and receiving transport layer packets.

util

Miscellaneous utilities for low-level networking.